﻿using System;
using Nexia.FluentHtmlElements.IoC;
using NUnit.Framework;
using Rhino.Mocks;

namespace FluentHtmlElements.Tests
{
	[TestFixture]
	public abstract class BaseFixture
	{
		[SetUp]
		public void MainSetup()
		{
			Mocks = new MockRepository();
			BeforeEachTest();
		}
		[TearDown]
		protected void MainTeardown()
		{
			DependencyFactory.Reset();
			AfterEachTest();
		}
		[TestFixtureSetUp]
		public void FixtureSetup()
		{
			BeforeAllTests();
		}
		[TestFixtureTearDown]
		public void FixtureTearDown()
		{
			AfterAllTests();
		}

		public MockRepository Mocks { get; private set; }

		protected virtual void BeforeEachTest() { }
		protected virtual void AfterEachTest() { }
		protected virtual void BeforeAllTests() { }
		protected virtual void AfterAllTests() { }

		protected T Dynamic<T>() where T : class
		{
			var mock = Mocks.DynamicMock<T>();
			if (typeof(T).IsInterface)
			{
				DependencyFactory.Inject(mock);
			}
			return mock;
		}

		protected T Strict<T>(params object[] parameters)
		{
			var mock = Mocks.StrictMock<T>(parameters);
			if (typeof(T).IsInterface)
			{
				DependencyFactory.Inject(mock);
			}
			return mock;
		}

		protected T Partial<T>(params object[] parameters) where T : class
		{
			return Mocks.PartialMock<T>(parameters);
		}

		protected T Stub<T>(params object[] parameters)
		{
			var stub = Mocks.Stub<T>(parameters);
			if (typeof(T).IsInterface)
			{
				DependencyFactory.Inject(stub);
			}
			return stub;
		}
		protected IDisposable Playback
		{
			get { return Mocks.Playback(); }
		}
		protected IDisposable Record
		{
			get { return Mocks.Record(); }
		}
		protected void ReplayAll()
		{
			Mocks.ReplayAll();
		}
		protected void Replay(object o)
		{
			Mocks.Replay(o);
		}
		protected void VerifyAll()
		{
			Mocks.VerifyAll();
		}

		//protected NameValueCollection CreateParameters(params string[] values)
		//    {
		//        if (values == null)
		//        {
		//            return new NameValueCollection(0);
		//        }
		//        if (values.Length % 2 != 0)
		//        {
		//            throw new ArgumentException("Expecting an even number of values");
		//        }
		//        var nvc = new NameValueCollection(values.Length / 2);
		//        for (int i = 0; i < values.Length; i += 2)
		//        {
		//            nvc.Add(values, values[i + 1]);
		//        }
		//        return nvc;
		//    }

		//recurse through the base type to find the field f you have to
		//protected void SetField(object o, string fieldName, object value)
		//{
		//  FieldInfo field = null;
		//  for (var type = o.GetType(); field == null && type.BaseType != null; type = type.BaseType)
		//  {
		//    field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
		//  }
		//  if (field == null)
		//  {
		//    throw new ArgumentException("Couldn't not find field with that name");
		//  }
		//  field.SetValue(o, value);
		//}
	}
}
